package com.bbcare.plat.support.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;

import org.apache.axis.AxisProperties;
import org.apache.axis.client.Call;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.bbcare.comm.AppException;
import com.bbcare.comm.Constants;
import com.bbcare.comm.ErrorCode;
import com.bbcare.comm.HttpUtil;
import com.bbcare.comm.SysException;
import com.bbcare.comm.ToolUtils;
import com.bbcare.followup.plat.entity.BsServiceDict;
import com.bbcare.followup.plat.store.ibatis.IConfCacheDAO;
import com.bbcare.plat.support.service.IBizInterAsClient;

/**
 * 调用外部接口服务类
 *
 * @date 2017.5.29
 * @author DemonLee
 */
@Service
public class BizInterAsClient implements IBizInterAsClient {

	private static Log log = LogFactory.getLog(BizInterAsClient.class);

	@Autowired
	private IConfCacheDAO confCacheDao;

	/**
	 * 根据服务判断服务类型,进行服务调用选择，custIdValue暂未启用，后续路由可能需要
	 */
	public String call(String serviceName, String custIdValue, Map<String, Object> inPparams)
			throws SysException, AppException {
		String retMsg = null;
		try {
			Map<String, Object> mapIn = new HashMap<String, Object>();
			mapIn.put("serviceName", serviceName);
			mapIn.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
			List<BsServiceDict> servList = confCacheDao.getServiceDictByServName(mapIn);
			if (CollectionUtils.isEmpty(servList)) {
				throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SERVICEDICT_IS_NOT_EXIST, "服务名对应接口未配置！"));
			}
			BsServiceDict bsdVo = servList.get(0);
			String serviceType = bsdVo.getServiceType();
			if (Constants.SERVICE_TYPE_HSF.equals(serviceType)) {
				// 待扩展
				// retMsg = callService(bsdVo, custIdValue, inPparams);
			} else if (Constants.SERVICE_TYPE_ESB.equals(serviceType)) {
				// ESB调用
				// retMsg = callServiceEsb(bsdVo, custIdValue, inPparams);
			} else if (Constants.SERVICE_TYPE_APP.equals(serviceType)) {
				// App接口调用
				retMsg = callServiceApp(bsdVo, custIdValue, inPparams);
			} else if (Constants.SERVICE_TYPE_ESBWSDL.equals(serviceType)) {
				retMsg = callServiceEsbGFY(bsdVo, custIdValue, inPparams);
				log.info("inPparams" + inPparams.toString());
			} else {
				// 待扩展
				// retMsg = callInform(bsdVo, custIdValue, inPparams);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppException(ErrorCode.EXCEPTION_TYPE_SYSTEM_SERVICE_CALL_EXCP,
					"BizInterAsClient:call():" + e.getMessage());
		}
		return retMsg;
	}

	/**
	 * 调用能力开放平台HSF
	 *
	 * @param params
	 * @return
	 * @throws SysException
	 * @throws AppException
	 */
	public String callService(BsServiceDict bsdVo, String custIdValue, String inPparams)
			throws SysException, AppException {
		String retMsg = null;
		try {
			//
		} catch (Exception e) {
			e.printStackTrace();
			throw new SysException(ErrorCode.EXCEPTION_TYPE_SYSTEM_SERVICE_CALL_EXCP,
					"BizInterAsClient:callService():" + e.getMessage(), e);
		}
		return retMsg;
	}

	/**
	 * 调用消息中间件
	 *
	 * @param params
	 * @return
	 * @throws SysException
	 * @throws AppException
	 */
	public String callInform(BsServiceDict bsdVo, String custIdValue, String inPparams)
			throws SysException, AppException {
		String retMsg = null;
		try {
			//
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		}
		return retMsg;
	}

	/**
	 * 调用ESB-rest服务
	 *
	 * @param params
	 * @return
	 * @throws SysException
	 * @throws AppException
	 */
	public String callServiceEsb(BsServiceDict bsdVo, String custIdValue, String servParam)
			throws SysException, AppException {
		String retMsg = null;
		try {
			String methodName = bsdVo.getMethodName();
			String serviceAddress = bsdVo.getServiceAddress();
			log.info("custIdValue=" + custIdValue + ", ESB服务调用开始:" + serviceAddress + "  " + methodName + "  "
					+ servParam);
			if (StringUtils.isEmpty(methodName)) {
				retMsg = HttpUtil.postData(serviceAddress, servParam);
			} else {
				retMsg = HttpUtil.postData(serviceAddress + "/" + methodName, servParam);
			}
			log.info("custIdValue=" + custIdValue + ", ESB服务调用返回值:" + serviceAddress + "  " + methodName + "  "
					+ retMsg);
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppException(ErrorCode.EXCEPTION_TYPE_SYSTEM_SERVICE_CALL_EXCP,
					"BizInterAsClient:callServiceEsb(" + bsdVo.getServiceAddress() + "):" + e.getMessage());
		}
		return retMsg;
	}

	/**
	 * 调用ESB服务 国妇婴
	 *
	 * @param params
	 * @return
	 * @throws SysException
	 * @throws AppException
	 */
	public String callServiceEsbGFY(BsServiceDict bsdVo, String custIdValue, Map<String, Object> servParam)
			throws SysException, AppException {
		// System.out.println("servParam"+servParam.toString());
		Map<String, Object> map = new HashMap<String, Object>(servParam);
		// 去除多余的字段
		servParam.remove("code");
		servParam.remove("type");// 类型 0：国妇婴预约类接口 ； 1：国妇婴选卡类
		String retMsg = null;
		log.info("wwwwww" + servParam.toString());
		String serviveCode = (String) map.get("code");
		String type = String.valueOf(map.get("type"));
		// String soapActionURI = "http://tempuri.org/selectVIN";
		// 处理入参
		String str = "<?xml version=\"1.0\" encoding=\"gb2312\"?><rows><row ";
		Set<String> keys = servParam.keySet();
		log.info("循环开始："+System.currentTimeMillis());
		if (keys != null) {
			Iterator<String> iterator = keys.iterator();
			while (iterator.hasNext()) {
				String key = iterator.next();
				str = str + key + "=" + "\"" + servParam.get(key) + "\"" + " ";
			}
			str = str + "></row></rows>";
		}
		log.info("循环结束：："+System.currentTimeMillis());
		String endpoint = bsdVo.getServiceAddress();
		String methodStr = bsdVo.getMethodName();
		String input = bsdVo.getInParam();
		String namespace = bsdVo.getTargetNamespace();
		String password = "";
		try {
			log.info("替换开始："+System.currentTimeMillis());
			input = input.replace(Constants.STRING_CHARACTER_GFY, str);
			if (type.equals("0")) {
				// 用户密码替换，预约接口
				password = ToolUtils.MD5Encrept(Constants.STRING_USERPASSWORD_ORDERINFO, Constants.INTEGER_FORMD5_32);
				input = input.replace(Constants.STRING_APPCODEINFO_GFY, Constants.STRING_0035EBSYUE_KEY);
			} else {
				//	查询卡接口
				password = ToolUtils.MD5Encrept(Constants.STRING_USERPASSWORD_INFO, Constants.INTEGER_FORMD5_32);
				input = input.replace(Constants.STRING_APPCODEINFO_GFY, Constants.STRING_0034ERBSFD_KEY);
			}
			input = input.replace(Constants.STRING_USERPASSWORD_GFY, password);
			// 当前时间替换
			Date date = new Date();
			SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");// 设置日期格式
			String dateFormat = df.format(date);
			input = input.replace(Constants.STRING_CREATETIMEINFO_GFY, dateFormat);
			/**
			 * 1、A = 变量用户MD5密钥值转为UTF8字符串 2、B = 变量报文时间戳值转为UTF8字符串 3、C = 变量业务逻辑
			 * 3、D = A与B异或运算,运算时计算长度以A和B值中字符长度短的为准，将D的值转为BASE64字符串
			 **/
		/*	dateFormat = URLEncoder.encode(df.format(date), "UTF-8");
			password = URLEncoder.encode(password, "UTF-8");*/
			log.info("$$$$$$$$$$$$:" + password +"   dateFormat : "+ dateFormat);
			String baseInfo = ToolUtils.twoStringXor(password, dateFormat).toLowerCase();
			log.info("baseInfo#######333 : " + baseInfo);

			// 计算最后签名的值
			String character = ToolUtils.changeToSHA(str, Constants.STRING_FORHASHCODE_256).toLowerCase();
			log.info("character   : " + character);
			String sign = ToolUtils.changeToSHA(character + baseInfo, Constants.STRING_FORHASHCODE_256).toLowerCase();
			// 将模板中的签名替换掉
			input = input.replace(Constants.STRING_SIGNINPUT_GFY, sign);
			// 替换调用接口code
			log.info("serviveCode$$$$$$$$$$$$" + serviveCode);
			input = input.replace(Constants.STRING_SERVICECODE_GFY, serviveCode);
			log.info("input==" + input);
			log.info("替换结束："+System.currentTimeMillis());
			AxisProperties.setProperty("axis.socketSecureFactory",
					"org.apache.axis.components.net.SunFakeTrustSocketFactory");
			org.apache.axis.client.Service service = new org.apache.axis.client.Service();
			Call call = (Call) service.createCall();
			call.setTargetEndpointAddress(new java.net.URL(endpoint));
			call.setOperationName(new QName(namespace, methodStr));
			call.setUseSOAPAction(true);
			call.setSOAPActionURI(namespace + methodStr);
			call.addParameter(new QName(namespace, "Message"), org.apache.axis.encoding.XMLType.XSD_STRING,
					javax.xml.rpc.ParameterMode.IN);
			call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);
			retMsg = (String) call.invoke(new Object[] { input });
			log.info("发送请求结束："+System.currentTimeMillis());
		} catch (Exception e) {
			retMsg = "10000";
			e.printStackTrace();
			throw new SysException("", "XmlException:OrderReceive.buildOrderReceiveXML():" + e.getMessage(), e);
		}
		return retMsg;

	}

	/**
	 * 调用app侧接口服务
	 *
	 * @param params
	 * @return
	 * @throws SysException
	 * @throws AppException
	 */
	public String callServiceApp(BsServiceDict bsdVo, String custIdValue, Map<String, Object> servParam)
			throws SysException, AppException {
		String retMsg = null;
		try {
			String methodName = bsdVo.getMethodName();
			String serviceAddress = bsdVo.getServiceAddress();
			if (StringUtils.isEmpty(methodName)) {
				retMsg = HttpUtil.postDataText(serviceAddress, servParam);
			} else {
				retMsg = HttpUtil.postDataText(serviceAddress + "/" + methodName, servParam);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppException(ErrorCode.EXCEPTION_TYPE_SYSTEM_SERVICE_CALL_EXCP,
					"BizInterAsClient:callServiceApp(" + bsdVo.getServiceAddress() + "):" + e.getMessage());
		}
		return retMsg;
	}

	/**
	 * 调用ESB服务 国妇婴 使用axis2调用
	 *
	 * @param params
	 * @return
	 * @throws SysException
	 * @throws AppException
	 */
	public String callServiceEsbInfo(BsServiceDict bsdVo, String custIdValue, Map<String, Object> servParam)
			throws SysException, AppException {
		// System.out.println("servParam"+servParam.toString());
		String retMsg = null;
		String serviveCode = (String) servParam.get("code");
		servParam.remove("code");
		// String soapActionURI = "http://tempuri.org/selectVIN";
		// 处理入参
		String str = "<?xml version=\"1.0\" encoding=\"gb2312\"?><rows><row ";
		Set<String> keys = servParam.keySet();
		if (keys != null) {
			Iterator<String> iterator = keys.iterator();
			while (iterator.hasNext()) {
				String key = iterator.next();
				str = str + key + "=" + "\"" + servParam.get(key) + "\"" + " ";
			}
			str = str + "></row></rows>";
		}
		String endpoint = bsdVo.getServiceAddress();
		String methodStr = bsdVo.getMethodName();
		String arg0 = bsdVo.getInParam();
		try {
			arg0 = arg0.replace(Constants.STRING_CHARACTER_GFY, str);
			// 用户密码替换
			String password = ToolUtils.MD5Encrept(Constants.STRING_USERPASSWORD_INFO, Constants.INTEGER_FORMD5_32);
			arg0 = arg0.replace(Constants.STRING_USERPASSWORD_GFY, password);
			// 当前时间替换
			Date date = new Date();
			SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");// 设置日期格式
			String dateFormat = df.format(date);
			log.info("dateFormat@@@@@@" + dateFormat);
			arg0 = arg0.replace(Constants.STRING_CREATETIMEINFO_GFY, dateFormat);
			/**
			 * 1、A = 变量用户MD5密钥值转为UTF8字符串 2、B = 变量报文时间戳值转为UTF8字符串 3、C = 变量业务逻辑
			 * 3、D = A与B异或运算,运算时计算长度以A和B值中字符长度短的为准，将D的值转为BASE64字符串
			 **/
			String baseInfo = ToolUtils.twoStringXor(password, dateFormat);
			log.info("baseInfo#######333 : " + baseInfo);

			// 计算最后签名的值
			String character = ToolUtils.changeToSHA(str, Constants.STRING_FORHASHCODE_256);
			String sign = ToolUtils.changeToSHA(character + baseInfo, Constants.STRING_FORHASHCODE_256);
			// 将模板中的签名替换掉
			arg0 = arg0.replace(Constants.STRING_SIGNINPUT_GFY, sign);
			// 替换调用接口code
			log.info("serviveCode$$$$$$$$$$$$" + serviveCode);
			arg0 = arg0.replace(Constants.STRING_SERVICECODE_GFY, serviveCode);
			log.info("111111111111111111111111111111111111111111111111111111111111");
			log.info("input==" + arg0);
			log.info("222222222222222222222222222222222222222222222222222222222222");
			AxisProperties.setProperty("axis.socketSecureFactory",
					"org.apache.axis.components.net.SunFakeTrustSocketFactory");
			org.apache.axis.client.Service service = new org.apache.axis.client.Service();
			Call call = (Call) service.createCall();
			String endpoint1 = "http://IPMCH.ESB.TopSchemaV2";
			call.setOperationName(new QName(endpoint1, methodStr));
			call.setUseSOAPAction(true);
			call.setSOAPActionURI("http://IPMCH.ESB.TopSchemaV2/CallESB");
			call.addParameter("arg0", org.apache.axis.encoding.XMLType.XSD_STRING, ParameterMode.IN);
			call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);
			call.setTargetEndpointAddress(new java.net.URL(endpoint));
			retMsg = (String) call.invoke(new Object[] { arg0 });
		} catch (Exception e) {
			retMsg = "10000";
			e.printStackTrace();
			throw new SysException("", "XmlException:OrderReceive.buildOrderReceiveXML():" + e.getMessage(), e);
		}
		return retMsg;

	}

}
